/**
 * 
 */
package com.zufangbao.earth.web.controller.finance;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import com.demo2do.core.persistence.support.Filter;
import com.demo2do.core.utils.DateUtils;
import com.demo2do.core.web.interceptor.InfoMessage;
import com.demo2do.core.web.interceptor.MenuSetting;
import com.demo2do.core.web.resolver.Page;
import com.demo2do.core.web.resolver.Secure;
import com.zufangbao.earth.entity.security.Principal;
import com.zufangbao.sun.entity.contract.Contract;
import com.zufangbao.sun.entity.factoring.AssetPackage;
import com.zufangbao.sun.entity.factoring.FactoringContract;
import com.zufangbao.sun.entity.factoring.SettleAssetPackagePaymentRecord;
import com.zufangbao.sun.entity.factoring.SettleItem;
import com.zufangbao.sun.entity.factoring.SettleRecord;
import com.zufangbao.sun.entity.finance.Charge;
import com.zufangbao.sun.entity.finance.FinancePaymentRecord;
import com.zufangbao.sun.entity.order.Order;
import com.zufangbao.sun.service.AssetPackageService;
import com.zufangbao.sun.service.ChargeService;
import com.zufangbao.sun.service.FactoringContractService;
import com.zufangbao.sun.service.FinancePaymentRecordService;
import com.zufangbao.sun.service.OrderService;
import com.zufangbao.sun.service.SettleItemService;
import com.zufangbao.sun.service.SettleRecordService;

/**
 * @author mohanlan
 *
 */
@Controller
@RequestMapping("/distribution")
@MenuSetting("menu-finance")
public class DistributionController {
	
	private static final String REDIRECT_DISTRIBUTION_HISTORY = "redirect:/distribution/history";
	@Autowired
	private FactoringContractService factoringContractService;
	@Autowired
	private FinancePaymentRecordService financePaymentRecordService;
	@Autowired
	private SettleItemService settleItemService;
	@Autowired
	private SettleRecordService settleRecordService;
	@Autowired
	private OrderService orderService;
	@Autowired
	private AssetPackageService assetPackageService;
	@Autowired
	private ChargeService chargeService;
	
	
	
	/**
	 * return settlement list
	 * 
	 * @return
	 */
	@RequestMapping(value = {"", "/settlement"})
	@MenuSetting("submenu-distribution-settlement")
	public ModelAndView settlement(){
		
		ModelAndView modelAndView = new ModelAndView("finance/distribution/settlement");
		
		return modelAndView;
		
	}
	
	/**
	 * return settlement list
	 * 
	 * @return
	 */
	@RequestMapping("/settlement/confirm")
	@MenuSetting("submenu-distribution-settlement")
	@InfoMessage("info.settle-record.create.success")
	public String confirmSettlement(@RequestParam("contractNo")String contractNo, @RequestParam("settleDate")String settleDate, @RequestParam("comment")String comment, @Secure Principal principal){
		
		Date settlementDate = DateUtils.parseDate(settleDate, "yyyy/MM/dd HH:mm:SS");
		FactoringContract factoringContract = factoringContractService.getFactoringContract(contractNo);
		List<FinancePaymentRecord> financePaymentRecords = financePaymentRecordService.getFinancePaymentRecordListForPrepareSettle(factoringContract, settlementDate);
		if (financePaymentRecords.isEmpty()){
			return REDIRECT_DISTRIBUTION_HISTORY;
		}
		List<SettleAssetPackagePaymentRecord> settleAssetPackagePaymentRecords = create_asset_payment_list(financePaymentRecords);
		
		SettleRecord settleRecord = factoringContract.settleExecution(settleAssetPackagePaymentRecords);
		factoringContractService.update(factoringContract.updateLastSettleTime(settlementDate));
		settleRecordService.save(settleRecord.updateSettle(comment, settlementDate, factoringContract, principal.getId()));
		List<SettleItem> settleItems = settleRecord.getSettleItemList();
		for(SettleItem settleItem : settleItems){
			settleItemService.save(settleItem.updateSettle(settlementDate,settleRecord));
			assetPackageService.update(settleItem.getAssetPackage());
			//settleItemService.save(settleItem.updateSettle(settlementDate,settleRecord));
		}
		for(FinancePaymentRecord financePaymentRecord : financePaymentRecords){
			orderService.update(financePaymentRecord.getOrder().updateSettled());
		}
		
		return REDIRECT_DISTRIBUTION_HISTORY;
						
	}

	/**
	 * @param financePaymentRecords
	 * @return
	 */
	private List<SettleAssetPackagePaymentRecord> create_asset_payment_list(
			List<FinancePaymentRecord> financePaymentRecords) {
		List<SettleAssetPackagePaymentRecord> settleAssetPackagePaymentRecords = new ArrayList<SettleAssetPackagePaymentRecord>();
		for(FinancePaymentRecord financePaymentRecord : financePaymentRecords){
			Contract contract = financePaymentRecord.getOrder().getContract();
			AssetPackage assetPackage = financePaymentRecordService.getAssetPackagesByFinancePaymentRecords(contract);
			if(assetPackage != null){
				SettleAssetPackagePaymentRecord settleAssetPackagePaymentRecord = new SettleAssetPackagePaymentRecord(assetPackage, financePaymentRecord);
				settleAssetPackagePaymentRecords.add(settleAssetPackagePaymentRecord);
			}
		}
		return settleAssetPackagePaymentRecords;
	}
	
	/**
	 * return settlement list
	 * 
	 * @return
	 */
	@RequestMapping(value = "/settlement/do", method=RequestMethod.POST)
	@MenuSetting("submenu-distribution-settlement")
	public ModelAndView doSettlement(@RequestParam("contractNo")String contractNo, @RequestParam("settleDate")String settleDate){
		
		ModelAndView modelAndView = new ModelAndView("finance/distribution/settlement");
		modelAndView.addObject("contractNo", contractNo);
		modelAndView.addObject("settleDate", settleDate);
		
		Date settlementDate = DateUtils.parseDate(settleDate, "yyyy/MM/dd HH:mm:SS");
		FactoringContract factoringContract = factoringContractService.getFactoringContract(contractNo);
		if(factoringContract == null){
			return modelAndView;
		}

		attach_dynamic_action_info(factoringContract);
		
		// 进行本次清分所需要的 正常回款的应收款和相关联的资产包信息
		List<FinancePaymentRecord> financePaymentRecords = financePaymentRecordService.getFinancePaymentRecordListForPrepareSettle(factoringContract, settlementDate);
		List<SettleAssetPackagePaymentRecord> settleAssetPackagePaymentRecords = create_asset_payment_list(financePaymentRecords);
		
		//显示清分界面
		SettleRecord settleRecord = factoringContract.settleExecution(settleAssetPackagePaymentRecords);
		List<SettleItem> settleItems = settleRecord.getSettleItemList();
		BigDecimal lenderTotal = settleRecord.getTotalPayInt().add(settleRecord.getTotalPayOstdAmt());
		BigDecimal borrowerTotal = settleRecord.getTotalPayRemant();
		
		modelAndView.addObject("settleRecord", settleRecord);
		modelAndView.addObject("settleItems", settleItems);
		modelAndView.addObject("factoringContract", factoringContract);
		modelAndView.addObject("lenderTotal", lenderTotal);
		modelAndView.addObject("borrowerTotal", borrowerTotal);
		modelAndView.addObject("settlementDate", settlementDate);
				
		return modelAndView;
		
	}

	/**
	 * 添加附加动态业务执行情况
	 * @param factoringContract
	 */
	private void attach_dynamic_action_info(FactoringContract factoringContract) {
		//设置关联附加动态记录
		//加入资产包信息
		List<AssetPackage> asset_package_list= financePaymentRecordService.getAvailableAssetPackageList(factoringContract);
		factoringContract.setAssetPackageList(asset_package_list);
		
		// 已收到的应收款信息
		List<FinancePaymentRecord> allFinancePaymentRecord = financePaymentRecordService
				.getFinancePaymentRecordList(factoringContract);
		factoringContract.setFinancePaymentRecordList(allFinancePaymentRecord);

		// 保证金扣款列表
		List<Charge> charge_list= chargeService.getChargeRecordsByFactoringContractId(factoringContract.getId()) ;
		factoringContract.setChargeList(charge_list);
	}
	
	@RequestMapping(value = "/settlement/print")
	@MenuSetting("submenu-distribution-settlement")
	public ModelAndView showSettlementPrint(@RequestParam("contractNo")String contractNo, @RequestParam("settleDate")String settleDate) {
			
		Date settlementDate = DateUtils.parseDate(settleDate, "yyyy/MM/dd HH:mm:SS");
		FactoringContract factoringContract = factoringContractService.getFactoringContract(contractNo);
		List<FinancePaymentRecord> financePaymentRecords = financePaymentRecordService.getFinancePaymentRecordListForPrepareSettle(factoringContract, settlementDate);
		List<SettleAssetPackagePaymentRecord> settleAssetPackagePaymentRecords = create_asset_payment_list(financePaymentRecords);
		
		SettleRecord settleRecord = factoringContract.settleExecution(settleAssetPackagePaymentRecords);
		List<SettleItem> settleItems = settleRecord.getSettleItemList();
		BigDecimal lenderTotal = settleRecord.getTotalPayInt().add(settleRecord.getTotalPayOstdAmt()).add(settleRecord.getTotalArDepositInputAmt());
		BigDecimal borrowerTotal = settleRecord.getTotalDepositDeductAmt().add(settleRecord.getTotalPayRemant());
		ModelAndView modelAndView = new ModelAndView("finance/distribution/settlement-detail-print");
		modelAndView.addObject("contractNo", contractNo);
		modelAndView.addObject("settleDate", settleDate);
		modelAndView.addObject("settleRecord", settleRecord);
		modelAndView.addObject("settleItems", settleItems);
		modelAndView.addObject("factoringContract", factoringContract);
		modelAndView.addObject("lenderTotal", lenderTotal);
		modelAndView.addObject("borrowerTotal", borrowerTotal);
		modelAndView.addObject("time",settlementDate);
		modelAndView.addObject("settlementDate", settlementDate);
		
		
		return modelAndView;
	}
	
	
	
	/**
	 * return distibution hisoty list
	 * 
	 * @return
	 */
	@RequestMapping("/history")
	@MenuSetting("submenu-distribution-history")
	public ModelAndView history(@Secure Principal principal, Page page){
		
		Filter filter = new Filter();
		if(principal.getAuthority().equals("ROLE_APP")){
			filter.addEquals("factoringContract.app.id", principal.getKeyId());
		}
		List<SettleRecord> settleRecords = settleRecordService.list(SettleRecord.class, filter.addEquals("disabled", false), page);
		for(SettleRecord settleRecord : settleRecords){
			settleRecordService.updateSettleRecordItemList(settleRecord);
		}
		
		ModelAndView modelAndView = new ModelAndView("finance/distribution/history");
		modelAndView.addObject("settleRecords", settleRecords);
		modelAndView.addObject("principal", principal);
		
		return modelAndView;
		
	}
	
	/**
	 * return distibution hisoty list
	 * 
	 * @return
	 */
	@RequestMapping("/history/search")
	@MenuSetting("submenu-distribution-history")
	public ModelAndView searchHistory(@RequestParam(value="start", required = false)String start, @RequestParam(value="end", required = false)String end, @RequestParam(value="contractNo", required = false)String contractNo, Page page,@Secure Principal principal){
		
		Filter filter = new Filter();
		if(!start.isEmpty()){
			Date startDate = DateUtils.addDays(DateUtils.parseDate(start, "yyyy-MM-dd"), 1);
			filter.addGreaterThan("settleAt", startDate);
		}
		if(!end.isEmpty()){
			Date endDate = DateUtils.addDays(DateUtils.parseDate(end, "yyyy-MM-dd"), 1);
			filter.addLessThan("settleAt", endDate);
		}
		if(!contractNo.isEmpty()){
			filter.addEquals("factoringContract.contractNo", contractNo);
		}
		
		if(principal.getAuthority().equals("ROLE_APP")){
			filter.addEquals("factoringContract.app.id", principal.getKeyId());
		}
		
		List<SettleRecord> settleRecords = settleRecordService.list(SettleRecord.class, filter.addEquals("disabled", false), page);
		for(SettleRecord settleRecord : settleRecords){
			settleRecordService.updateSettleRecordItemList(settleRecord);
		}
		
		ModelAndView modelAndView = new ModelAndView("finance/distribution/history");
		modelAndView.addObject("start", start);
		modelAndView.addObject("end", end);
		modelAndView.addObject("contractNo", contractNo);
		modelAndView.addObject("settleRecords", settleRecords);
		
		return modelAndView;
		
	}
	
	/**
	 * return distibution hisoty list
	 * 
	 * @return
	 */
	@RequestMapping("/history/{settleRecordId}/detail")
	@MenuSetting("submenu-distribution-history")
	public ModelAndView settleRecordDetail(@PathVariable("settleRecordId")Long settleRecordId){
		
		SettleRecord settleRecord = settleRecordService.load(SettleRecord.class, settleRecordId);
		settleRecordService.updateSettleRecordItemList(settleRecord);
		FactoringContract factoringContract = settleRecord.getFactoringContract();
		attach_dynamic_action_info(factoringContract);
		List<SettleItem> settleItems = settleRecord.getSettleItemList();
		BigDecimal lenderTotal = settleRecord.getTotalPayInt().add(settleRecord.getTotalPayOstdAmt()).add(settleRecord.getTotalArDepositInputAmt());
		BigDecimal borrowerTotal = settleRecord.getTotalDepositDeductAmt().add(settleRecord.getTotalPayRemant());
		ModelAndView modelAndView = new ModelAndView("finance/distribution/history-detail");
		modelAndView.addObject("settleRecord", settleRecord);
		modelAndView.addObject("settleItems", settleItems);
		modelAndView.addObject("factoringContract", factoringContract);
		modelAndView.addObject("lenderTotal", lenderTotal);
		modelAndView.addObject("borrowerTotal", borrowerTotal);
				
		return modelAndView;
		
	}
	
	/**
	 * cancel settle record 
	 * @return
	 */
	@RequestMapping("/{settleRecordId}/cancel")
	public ModelAndView cancel(@PathVariable("settleRecordId")Long settleRecordId) {
		
		ModelAndView modelAndView = new ModelAndView("finance/distribution/settle-record-cancel");
		modelAndView.addObject("settleRecordId", settleRecordId);
		
		return modelAndView;
	}
	
	/**
	 * support transaction record 
	 * @return
	 */
	@RequestMapping(value="/{settleRecordId}/cancel", method = RequestMethod.POST)
	@MenuSetting("submenu-distribution-history")
	@InfoMessage("info.settle-record.cancel.success")
	public String onCancle(Page page, @PathVariable("settleRecordId")Long settleRecordId, @Secure Principal principal) {
		
		SettleRecord settleRecord = settleRecordService.load(SettleRecord.class, settleRecordId);		
		settleRecordService.updateSettleRecordItemList(settleRecord);
		List<SettleItem> settleItemList = settleRecord.getSettleItemList();
		for(SettleItem settleItem : settleItemList){
			FinancePaymentRecord preFinancePaymentRecord = financePaymentRecordService.getPreFinancePaymentRecordWithNormalRepayment(settleItem.getFinancePaymentRecord());
			settleItem.setPreFinancePaymentRecord(preFinancePaymentRecord);
			AssetPackage assetPackage = financePaymentRecordService.getAssetPackagesByFinancePaymentRecords(settleItem.getFinancePaymentRecord().getOrder().getContract());
			settleItem.setAssetPackage(assetPackage);
			settleItemService.update(settleItem);
		}
		settleRecordService.updateSettleRecordItemList(settleRecord);
		FactoringContract factoringContract = settleRecord.getFactoringContract();
		Date now = new Date();
		factoringContract.undoSettleAction(settleRecord, now, principal.getId());
		factoringContractService.update(factoringContract);
		settleRecordService.update(settleRecord);
		List<SettleItem> settleItems = settleRecord.getSettleItemList();
		for(SettleItem settleItem : settleItems){
			settleItemService.update(settleItem);
			assetPackageService.update(settleItem.getAssetPackage());
			Order order = settleItem.getFinancePaymentRecord().getOrder();
			orderService.update(order.cancelSettled());
		}
		
		return REDIRECT_DISTRIBUTION_HISTORY;
	}
	
}
